package com.yf.mediaserver.gb.sip.processors.req.impl;

import cn.hutool.crypto.digest.MD5;
import com.yf.mediaserver.gb.sip.processors.SIPProcessorObserver;
import com.yf.mediaserver.gb.sip.processors.SIPSender;
import com.yf.mediaserver.gb.sip.processors.req.ISIPRequestProcessor;
import com.yf.mediaserver.gb.sip.processors.req.SIPRequestProcessorParent;
import gov.nist.javax.sip.header.Authorization;
import gov.nist.javax.sip.header.SIPDate;
import gov.nist.javax.sip.header.SIPDateHeader;
import gov.nist.javax.sip.header.WWWAuthenticate;
import gov.nist.javax.sip.message.SIPRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sip.RequestEvent;
import javax.sip.SipFactory;
import javax.sip.address.URI;
import javax.sip.header.ContactHeader;
import javax.sip.message.Response;
import java.time.Instant;
import java.util.Calendar;
import java.util.Locale;
import java.util.Random;

/**
 * SIP命令类型： REGISTER请求
 */
@Slf4j
@Component
public class RegisterRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {

    public final static String method = "REGISTER";

    @Resource
    private SIPProcessorObserver processorObserver;
    @Resource
    private SIPSender sipSender;

    @Override
    public void afterPropertiesSet() {
        processorObserver.addRequestProcessor(method, this);
    }

    /**
     * 收到注册请求 处理
     */
    @Override
    public void process(RequestEvent evt) {
        try {
            SIPRequest request = (SIPRequest) evt.getRequest();
            String hostAddress = request.getLocalAddress().getHostAddress();
            log.info("当前服务端地址:{}", hostAddress);
            Authorization authorization = request.getAuthorization();
            log.info("授权头：{}", authorization);
            if (authorization == null) {
                Response response = SipFactory.getInstance().createMessageFactory().createResponse(Response.UNAUTHORIZED, request);
                WWWAuthenticate wwwAuthenticate = new WWWAuthenticate();

                wwwAuthenticate.setParameter("realm", "4101050000");
                wwwAuthenticate.setParameter("qop", "auth");
//                String nonce = MD5.create().digestHex(RandomUtil.randomNumbers(14));
                long time = Instant.now().toEpochMilli();
                Random rand = new Random();
                long pad = rand.nextLong();
                String nonceString = Long.valueOf(time).toString() + Long.valueOf(pad).toString();
                String nonce  = MD5.create().digestHex(nonceString.getBytes());


                wwwAuthenticate.setParameter("nonce", nonce);
                wwwAuthenticate.setParameter("algorithm", "MD5");

                response.addHeader(wwwAuthenticate);
                log.info("未授权响应401");
                sipSender.simpleSend(hostAddress, response);
                return;
            }
//            nonce计数器，是一个16进制的数值，表示同一nonce下客户端发送出请求的数量
            int nc = authorization.getNonceCount();
            // qop 保护质量 包含auth（默认的）和auth-int（增加了报文完整性检测）两种策略
            String qop = authorization.getQop();
            // 客户端随机数，这是一个不透明的字符串值，由客户端提供，并且客户端和服务器都会使用，以避免用明文文本。
            // 这使得双方都可以查验对方的身份，并对消息的完整性提供一些保护
            String cNonce = authorization.getCNonce();

            String username = authorization.getUsername();
            String realm = authorization.getRealm();
            String a1 = String.format("%s:%s:%s", username,realm,"YF_GB_PWD");
            String ha1 = MD5.create().digestHex(a1);
            log.info("a1：{}",a1);
            log.info("sha1：{}",ha1);

            URI uri = authorization.getURI();
            String nonce = authorization.getNonce();
            String a2 = String.format("%s:%s", request.getMethod().toUpperCase(), uri);
            String ha2 = MD5.create().digestHex(a2);
            log.info("a2：{}",a2);
            log.info("sha2：{}",ha2);

            //Response = MD5(MD5(A1) + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + MD5(A2))
            String ncStr = String.format("%08x", nc).toUpperCase();
            String kd = String.format("%s:%s:%s:%s:%s:%s",ha1,nonce,ncStr,cNonce,qop,ha2);
            log.info("最终字符：{}",kd);

            String mdString = MD5.create().digestHex(kd);

            log.info("最终字符 加密：{}",mdString);

            String authResponse = authorization.getResponse();
            log.info("response：{}",authResponse);

            log.info("开始验证授权:{}",mdString.equals(authResponse));
            if(!mdString.equals(authResponse) ){
                log.warn(" 设备密码/SIP服务器ID错误, 回复403");
                Response response = SipFactory.getInstance().createMessageFactory().createResponse(Response.FORBIDDEN, request);
                response.setReasonPhrase("wrong password");
                sipSender.simpleSend(hostAddress,response);
                return;
            }
            if (request.getExpires() == null) {
                //如果没有过期时间
                log.warn("未设置过期时间,回复400");
                sipSender.simpleSend(hostAddress, SipFactory.getInstance().createMessageFactory().createResponse(Response.BAD_REQUEST, request));
                return;
            }

            // 携带授权头并且密码正确
            Response response = SipFactory.getInstance().createMessageFactory().createResponse(Response.OK, request);
            // 添加date头
            SIPDateHeader dateHeader = new SIPDateHeader();
            // 使用自己修改的
            dateHeader.setDate(new SIPDate(Calendar.getInstance(Locale.CHINESE).getTimeInMillis()));
            response.addHeader(dateHeader);
            // 添加Contact头
            response.addHeader(request.getHeader(ContactHeader.NAME));
            // 添加Expires头
            response.addHeader(request.getExpires());
            sipSender.simpleSend(hostAddress,response);

        } catch (Exception e) {
            log.error("未处理的异常 ", e);
        }
    }



}
